package com.ashes.belife.common.utils;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chengxuhui
 * @description 转义和反转义工具类
 */
@Slf4j
public class EasyExcelUtil<T> {

    private static final int MAX_SIZE = 900;

    /**
     * 下载excel
     *
     * @param response 响应
     * @param cls      cls
     * @param fileName 文件名称
     * @param data     数据
     * @throws IOException ioexception
     */
    public static <T> void downloadExcel(HttpServletResponse response, Class cls, String fileName, List<T> data) throws IOException {
        // 如果传入的data数据是空的话就让data成为一个空集合 变成下载导入模板
        if (CollUtil.isEmpty(data)) {
            data = new ArrayList<>();
        }
        try (OutputStream os = response.getOutputStream()) {
            setResponseHeader(response, fileName);
            EasyExcel.write(os)
                    .head(cls) //设置头信息
                    .useDefaultStyle(false) // 取消默认样式
                    .registerWriteHandler(null) // 设置导出样式
                    .sheet("导入模板")
                    .doWrite(data);
        } catch (IOException e) {
            log.error("下载导入模板异常{}", e);
            throw new IOException("下载导入模板异常");
        }
    }


    /**
     * 设置响应头
     *
     * @param response 响应
     * @param fileName 文件名称
     */
    public static void setResponseHeader(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        response.setHeader("Connection", "close");
        response.setHeader("Content-Type", "application/octet-stream");
    }

    /**
     * 解析excel和批量插入 调用ServiceImpl的默认方法进行插入操作  (目前不适用)
     *
     * @param file excel文件
     * @param cls  cls
     * @param impl impl
     */
//    public int parseExcelAndDoInsertBatch(MultipartFile file, Class cls, ServiceImpl impl) throws IOException {
//        List<T> resultList = new ArrayList<>();
//        try (InputStream inputStream = file.getInputStream()) {
//            EasyExcel.read(inputStream, cls, new ReadListener<T>() {
//                @Override
//                public void invoke(T t, AnalysisContext analysisContext) {
//                    resultList.add(t);
//                }
//
//                @Override
//                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//                }
//            }).sheet().doRead();
//            if (CollUtil.isNotEmpty(resultList)) {
//                List<List<T>> partition = Lists.partition(resultList, MAX_SIZE);
//                partition.forEach(impl::saveBatch);
//            }
//            return resultList.size();
//        }
//    }

    /**
     * 解析excel返回解析数据 解析数据之后如果有相关的操作建议使用此方法 如使用mapper的自动填充字段等
     *
     * @param file 文件                       前端传入文件
     * @param cls  cls                       需要解析的类的对象
     * @return {@link List}<{@link T}>       返回解析之后的泛型集合
     * @throws IOException ioexception       获取MultipartFile输入流有可能会导致IO异常
     */
    public static <T> List<T> parseExcel(MultipartFile file, Class cls) throws IOException {
        try (InputStream inputStream = file.getInputStream()) {
            List<T> resultList = new ArrayList<>();
            EasyExcel.read(inputStream, cls, new ReadListener<T>() {
                @Override
                public void invoke(T t, AnalysisContext analysisContext) {
                    resultList.add(t);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                    log.info("解析数据完成-{}\n", resultList);
                }
            }).sheet().doRead();
            return resultList;
        }
    }

    public static <T>  List<T> parseExcel(InputStream inputStream, Class cls) throws IOException {
        List<T> resultList = new ArrayList<>();
        EasyExcel.read(inputStream, cls, new ReadListener<T>() {
            @Override
            public void invoke(T t, AnalysisContext analysisContext) {
                resultList.add(t);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                log.info("解析数据完成-{}\n", resultList);
            }
        }).sheet().doRead();
        return resultList;
    }
}

